package com.mygame.game_server.cmdHandle;

import com.google.protobuf.GeneratedMessageV3;
import com.mygame.game_server.util.PackageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Jim
 * @date 23:26 2022/5/6
 * @description
 * @email:huwmz04153277@126.com
 */
public final class CmdHandlerFactory {

    private static Logger logger = LoggerFactory.getLogger(CmdHandlerFactory.class);


    /**
     * 命令处理器字典
     */
    volatile static private Map<Class<?>, ICmdHandler<? extends GeneratedMessageV3>> _handlerMap = new ConcurrentHashMap<>();

    private CmdHandlerFactory() {
    }

    static public void init() {
        logger.info("======完成处理器建立======");

        // 获取包名称
        final String packageName = CmdHandlerFactory.class.getPackage().getName();
        // 通过类名遍历class文件并反射获取所有实现类
        Set<Class<?>> classSet = PackageUtil.listSubClazz(packageName, true, ICmdHandler.class);
        for (Class<?> aClazz : classSet) {
            if (null == aClazz || 0 != (aClazz.getModifiers() & Modifier.ABSTRACT)) {
                continue;
            }
            Method[] methodArrays = aClazz.getDeclaredMethods();

            //消息类型
            Class<?> cmdClazz = null;

            for (Method method : methodArrays) {
                if (null == method || !method.getName().equals("handle")) {
                    continue;
                }

                // 获取方法参数类型
                Class<?>[] paramTypes = method.getParameterTypes();

                // 如果参数小于2并且是V3类型或者不是其子类
                if (paramTypes.length < 2
                        || paramTypes[1] == GeneratedMessageV3.class
                        || !GeneratedMessageV3.class.isAssignableFrom(paramTypes[1])) {
                    continue;
                }
                cmdClazz = paramTypes[1];
                //获取字段数组第一个字段注解
//                cmdClazz.getFields()[0].getAnnotation(MyAnnotation.class);
                //获取类的注解
//                cmdClazz.getAnnotation(MyAnnotation.class)
                break;
            }

            if (null == cmdClazz) {
                continue;
            }

            try {
                //创建实例
                ICmdHandler<?> newHandler = (ICmdHandler<?>) aClazz.newInstance();

                logger.info("{}<=====>{}", cmdClazz.getName(), newHandler.getClass().getName());
                _handlerMap.put(cmdClazz, newHandler);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }

        }

    }

    /**
     * 创建处理器
     *
     * @param msgClass
     * @return
     */
    public static ICmdHandler<? extends GeneratedMessageV3> getInstance(Class<?> msgClass) {
        if (null == msgClass) {
            return null;
        }
        return _handlerMap.get(msgClass);
    }
}
